﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using EnvDTE;
using System.Collections;
using SPVisualDev.VSAddin.Dialogs;

namespace SPVisualDev.VSAddin.UserControls
{
    internal partial class UCClassExplorer : UserControl
    {
        private Project m_startup_project;

        public UCClassExplorer()
        {
            InitializeComponent();

            ClassesTreeView.BeforeExpand += new TreeViewCancelEventHandler(ClassesTreeView_BeforeExpand);
        }

        public TreeView TreeView
        {
            get { return ClassesTreeView; }
        }

        public CodeClass SelectedNode
        {
            get
            {
                if (ClassesTreeView.SelectedNode == null)
                    return null;

                return ClassesTreeView.SelectedNode.Tag as CodeClass;
            }
        }

        public bool ShowOnlyProjectClasses
        {
            get;
            set;
        }

        public void Initialize(Project ParentProject)
        {
            m_startup_project = ParentProject;

            ClassesTreeView.Nodes.Clear();
        }

        public void RenderRootNode()
        {
            ClassesTreeView.Nodes.Clear();

            TreeNode topNode = new TreeNode("Solution projects");
            topNode.Name = null;
            topNode.Tag = null;
            topNode.ImageKey = "Folder";
            topNode.SelectedImageKey = "Folder";

            ClassesTreeView.Nodes.Add(topNode);
            ClassesTreeView.TopNode = topNode;

            Solution solution = m_startup_project.DTE.Solution;
            TreeNode selectedNode = null;

            foreach (Project project in solution.Projects)
            {
                if (this.ShowOnlyProjectClasses)
                {
                    if (project != m_startup_project)
                        continue;
                }

                TreeNode node = new TreeNode(project.Name);
                node.Name = project.Name;
                node.Tag = project;
                node.ImageKey = "Folder";
                node.SelectedImageKey = "Folder";

                if (project.Name == m_startup_project.Name)
                {
                    selectedNode = node;
                }

                ClassesTreeView.TopNode.Nodes.Add(node);

                TreeNode dummyNode = new TreeNode(string.Empty);
                dummyNode.Name = "__dummy__";

                node.Nodes.Add(dummyNode);
            }

            ClassesTreeView.TopNode.Expand();

            if (selectedNode != null)
            {
                selectedNode.Expand();
            }

            ClassesTreeView.Sort();
            ClassesTreeView.Refresh();
        }

        private void ClassesTreeView_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            try
            {
                if (e.Node.Tag == null)
                    return;

                if (e.Node.Nodes.Count != 1)
                {
                    if (e.Node.Nodes[0].Name != "__dummy__")
                        return;
                }

                e.Node.Nodes.Clear();

                if (e.Node.Tag is Project)
                {
                    Project p = e.Node.Tag as Project;

                    List<CodeNamespace> nsList = GetAllNamespacesInCollection(p.CodeModel.CodeElements);
                    foreach (CodeNamespace ns in nsList)
                    {
                        TreeNode node = new TreeNode(ns.FullName);
                        node.Name = ns.FullName;
                        node.Tag = ns;
                        node.SelectedImageKey = "Namespace";
                        node.ImageKey = "Namespace";

                        e.Node.Nodes.Add(node);

                        TreeNode dummyNode = new TreeNode(string.Empty);
                        dummyNode.Name = "__dummy__";

                        node.Nodes.Add(dummyNode);
                    }
                }
                else if (e.Node.Tag is CodeNamespace)
                {
                    CodeNamespace ns = e.Node.Tag as CodeNamespace;

                    foreach (CodeElement el in ns.Members)
                    {
                        if (this.ShowOnlyProjectClasses && el.InfoLocation != vsCMInfoLocation.vsCMInfoLocationProject)
                            continue;
                        
                        if (el is CodeClass)
                        {
                            CodeClass cls = el as CodeClass;
                            TreeNode node = new TreeNode(cls.Name);
                            node.Name = cls.FullName;
                            node.Tag = cls;
                            node.SelectedImageKey = "Class";
                            node.ImageKey = "Class";

                            e.Node.Nodes.Add(node);

                            //TreeNode dummyNode = new TreeNode(string.Empty);
                            //dummyNode.Name = "__dummy__";
                            //node.Nodes.Add(dummyNode);
                        }
                    }
                }

                //ClassesTreeView.Sort();
                ClassesTreeView.Refresh();
            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex);
            }
        }

        private List<CodeNamespace> GetAllNamespacesInCollection(CodeElements collection)
        {
            List<CodeNamespace> nsList = new List<CodeNamespace>();

            foreach (CodeElement element in collection)
            {
                CodeNamespace ns = element as CodeNamespace;
                if (ns != null)
                {
                    List<CodeClass> listOfCodeClasses = ns.Members.OfType<CodeClass>().ToList();
                    if (listOfCodeClasses.Count > 0)
                    {
                        bool b = listOfCodeClasses.Any(c => c.InfoLocation == vsCMInfoLocation.vsCMInfoLocationProject);
                        if (!b)
                            continue;

                        nsList.Add(ns);
                    }


                    List<CodeNamespace> subNamespaces = GetAllNamespacesInCollection(ns.Members);
                    if (subNamespaces.Count > 0)
                    {
                        nsList.AddRange(subNamespaces);
                    }
                }
            }

            return nsList;
        }
    }
}
